package cn.com.idmy.cloud.service.impl;

import cn.com.idmy.base.FieldGetter;
import cn.com.idmy.base.model.Page;
import cn.com.idmy.base.util.IdUtil;
import cn.com.idmy.base.util.SqlUtil;
import cn.com.idmy.cloud.service.DefaultService;
import cn.com.idmy.orm.core.*;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hutool.core.collection.CollUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;

@Slf4j
public class DefaultServiceImpl<D extends OrmDao<T, ID>, T, ID extends Serializable> implements DefaultService<T, ID> {
    @Autowired
    protected D dao;

    @Override
    public @NotNull Logger log() {
        return log;
    }

    public @NotNull TableInfo table() {
        return dao.table();
    }

    @Override
    public @NotNull ID newId() {
        var id = Tables.getId(dao.entityType());
        return IdUtil.getId(dao.idType(), dao.table().entityType(), id.value());
    }

    @Override
    public @Nullable T getNullable(@NotNull Query<T> q, @NotNull FieldGetter<T, ?> f1, @NotNull FieldGetter<T, ?> f2) {
        return dao.getNullable(q.select(f1, f2));
    }

    @Override
    public @Nullable T getNullable(@NotNull Query<T> q, @NotNull FieldGetter<T, ?> f1, @NotNull FieldGetter<T, ?> f2, @NotNull FieldGetter<T, ?> f3) {
        return dao.getNullable(q.select(f1, f2, f3));
    }

    @Override
    public @NotNull T get(@NotNull Query<T> q, @NotNull FieldGetter<T, ?> f1, @NotNull FieldGetter<T, ?> f2) {
        return dao.get(q.select(f1, f2));
    }

    @Override
    public @NotNull T get(@NotNull Query<T> q, @NotNull FieldGetter<T, ?> f1, @NotNull FieldGetter<T, ?> f2, @NotNull FieldGetter<T, ?> f3) {
        return dao.get(q.select(f1, f2, f3));
    }

    @Override
    public @NotNull List<T> list(@NotNull Query<T> q, @NotNull FieldGetter<T, ?> f1, @NotNull FieldGetter<T, ?> f2) {
        return dao.list(q.select(f1, f2));
    }

    @Override
    public @NotNull List<T> list(@NotNull Query<T> q, @NotNull FieldGetter<T, ?> f1, @NotNull FieldGetter<T, ?> f2, @NotNull FieldGetter<T, ?> f3) {
        return dao.list(q.select(f1, f2, f3));
    }

    @Override
    public boolean create(@NonNull T t) {
        return SqlUtil.toBoolean(dao.create(t));
    }

    @Override
    public boolean create(@NonNull Collection<T> ls) {
        return SqlUtil.toBoolean(dao.creates(ls));
    }

    @Override
    public boolean create(@NonNull Collection<T> ls, int size) {
        return SqlUtil.toBoolean(dao.creates(ls, size));
    }

    @Override
    public T copy(@NonNull ID id, @NotNull Consumer<T> consumer) {
        return dao.copy(id, consumer);
    }

    @Override
    public boolean update(@NonNull T t) {
        return SqlUtil.toBoolean(dao.update(t));
    }

    @Override
    public boolean update(@NonNull T t, boolean ignoreNull) {
        return SqlUtil.toBoolean(dao.update(t, ignoreNull));
    }

    @Override
    public boolean update(@Nullable Collection<T> ls, int size, boolean ignoreNull) {
        if (CollUtil.isEmpty(ls)) {
            return false;
        } else {
            return SqlUtil.toBoolean(dao.update(ls, size, ignoreNull));
        }
    }

    @Override
    public boolean update(@Nullable Collection<T> ls, boolean ignoreNull) {
        if (CollUtil.isEmpty(ls)) {
            return false;
        } else {
            return SqlUtil.toBoolean(dao.update(ls, 1000, ignoreNull));
        }
    }

    @Override
    public boolean update(@Nullable Collection<T> ls) {
        return update(ls, 1000, true);
    }

    @Override
    public boolean update(@NotNull Update<T> u) {
        return SqlUtil.toBoolean(dao.update(u));
    }

    @Override
    public boolean createOrUpdate(@NonNull T t) {
        return SqlUtil.toBoolean(dao.createOrUpdate(t));
    }

    @Override
    public boolean delete(@NonNull ID id) {
        return SqlUtil.toBoolean(dao.delete(id));
    }

    @Override
    public boolean delete(@Nullable Collection<ID> ids) {
        return SqlUtil.toBoolean(dao.delete(ids));
    }

    @Override
    public boolean delete(@NotNull Delete<T> d) {
        return SqlUtil.toBoolean(dao.delete(d));
    }


    @Override
    public @NotNull Query<T> q(boolean nullable) {
        return dao.q(nullable);
    }

    public @NotNull Query<T> q(@Nullable T params, boolean nullable) {
        return dao.q(nullable).common(params);
    }

    @Override
    public @NotNull Update<T> u(boolean nullable) {
        return dao.u(nullable);
    }

    @Override
    public @NotNull Delete<T> d(boolean nullable) {
        return dao.d(nullable);
    }

    @Override
    public long count(@NotNull Query<T> q) {
        return dao.count(q);
    }

    @Override
    public boolean has(@NotNull Query<T> q) {
        return dao.has(q);
    }

    @Override
    public boolean has(@NonNull ID id) {
        return dao.has(id);
    }

    @Override
    public void has(@NonNull ID id, @NotNull String msg, @NotNull Object... params) {
        dao.has(id, msg, params);
    }

    @Override
    public void has(@NotNull Query<T> q, @NotNull String msg, @NotNull Object... params) {
        dao.has(q, msg, params);
    }

    @Override
    public boolean notHas(@NotNull Query<T> q) {
        return dao.notHas(q);
    }

    @Override
    public boolean notHas(@NonNull ID id) {
        return dao.notHas(id);
    }

    @Override
    public void notHas(@NonNull ID id, @NotNull String msg, @NotNull Object... params) {
        dao.notHas(id, msg, params);
    }

    @Override
    public void notHas(@NotNull Query<T> q, @NotNull String msg, @NotNull Object... params) {
        dao.notHas(q, msg, params);
    }

    @Override
    public @NotNull List<T> list(@NotNull Query<T> q) {
        return dao.list(q);
    }

    @Override
    public @NotNull List<T> all() {
        return dao.all();
    }

    @Override
    public @NotNull List<T> list(@Nullable Collection<ID> ids) {
        return dao.list(ids);
    }

    @Override
    public @NotNull List<T> list(@NotNull Collection<ID> ids, @NotNull String msg, @NotNull Object... params) {
        return dao.list(ids, msg, params);
    }

    @Override
    public @NotNull <R> List<R> list(@NotNull FieldGetter<T, R> field, @Nullable Collection<ID> ids) {
        return dao.list(field, ids);
    }

    @Override
    public @NotNull <R> List<R> list(@NotNull FieldGetter<T, R> field, @NotNull Query<T> q) {
        return dao.list(field, q);
    }

    @Override
    public @Nullable T getNullable(@NotNull Query<T> q) {
        return dao.getNullable(q);
    }

    @Override
    public @NotNull T get(@NotNull Query<T> q, @NotNull String msg, @NotNull Object... params) {
        return dao.get(q, msg, params);
    }

    @Override
    public @NotNull T get(@NotNull Query<T> q) {
        return dao.get(q);
    }

    @Override
    public @Nullable T getNullable(@NonNull ID id) {
        return dao.getNullable(id);
    }

    @Override
    public @NotNull T get(@NonNull ID id) {
        return dao.get(id);
    }

    @Override
    public <R> @Nullable R getNullable(@NotNull FieldGetter<T, R> field, @NonNull ID id) {
        return dao.getNullable(field, id);
    }

    @Override
    public <R> @NotNull R get(@NotNull FieldGetter<T, R> field, @NonNull ID id) {
        return dao.get(field, id);
    }

    @Override
    public <R> @NotNull R get(@NotNull FieldGetter<T, R> field, @NonNull ID id, @NotNull String msg, @NotNull Object... params) {
        return dao.get(field, id, msg, params);
    }

    @Override
    public <R> @Nullable R getNullable(@NotNull FieldGetter<T, R> field, @NotNull Query<T> q) {
        return dao.getNullable(field, q);
    }

    @Override
    public <R> @NotNull R get(@NotNull FieldGetter<T, R> field, @NotNull Query<T> q, @NotNull String msg, @NotNull Object... params) {
        return dao.get(field, q, msg, params);
    }

    @Override
    public <R> @NotNull R get(@NotNull FieldGetter<T, R> field, @NotNull Query<T> q) {
        return dao.get(field, q);
    }

    @Override
    public @NotNull Map<ID, T> map(@Nullable ID[] ids) {
        return dao.map(ids);
    }

    @Override
    public @NotNull Map<ID, T> map(@Nullable Collection<ID> ids) {
        return dao.map(ids);
    }

    @Override
    public @NotNull <R> Map<R, T> map(@NotNull FieldGetter<T, R> key, @NotNull Query<T> q) {
        return dao.map(key, q);
    }

    @Override
    public @NotNull <K, V> Map<K, V> map(@NotNull FieldGetter<T, K> key, @NotNull FieldGetter<T, V> val, @NotNull Query<T> q) {
        return dao.map(key, val, q);
    }

    @Override
    public @NotNull <K, V> Map<K, List<V>> maps(@NotNull FieldGetter<T, K> key, @NotNull FieldGetter<T, V> val, @NotNull Query<T> q) {
        return dao.maps(key, val, q);
    }

    @Override
    public <R extends Number> @Nullable R abs(@NotNull FieldGetter<T, R> field, @NotNull Query<T> q) {
        return dao.abs(field, q);
    }

    @Override
    public <R extends Number> @Nullable R avg(@NotNull FieldGetter<T, R> field, @NotNull Query<T> q) {
        return dao.avg(field, q);
    }

    @Override
    public <R extends Number> @Nullable R max(@NotNull FieldGetter<T, R> field, @NotNull Query<T> q) {
        return dao.max(field, q);
    }

    @Override
    public <R extends Number> @Nullable R min(@NotNull FieldGetter<T, R> field, @NotNull Query<T> q) {
        return dao.min(field, q);
    }

    @Override
    public @NotNull BigDecimal sum(@NotNull FieldGetter<T, BigDecimal> field, @NotNull Query<T> q) {
        return dao.sum(field, q);
    }

    @Override
    public long sumLong(@NotNull FieldGetter<T, Long> field, @NotNull Query<T> q) {
        return dao.sumLong(field, q);
    }

    @Override
    public int sumInt(@NotNull FieldGetter<T, Integer> field, @NotNull Query<T> q) {
        return dao.sumInt(field, q);
    }

    @Override
    public @Nullable BigDecimal sumNullable(@NotNull FieldGetter<T, BigDecimal> field, @NotNull Query<T> q) {
        return dao.sumNullable(field, q);
    }

    @Override
    public @Nullable Long sumLongNullable(@NotNull FieldGetter<T, Long> field, @NotNull Query<T> q) {
        return dao.sumLongNullable(field, q);
    }

    @Override
    public @Nullable Integer sumIntNullable(@NotNull FieldGetter<T, Integer> field, @NotNull Query<T> q) {
        return dao.sumIntNullable(field, q);
    }

    @Override
    public @NotNull Page<T> page(@NonNull Page<?> in, @NotNull Query<T> q) {
        return dao.page(in, q);
    }
}